package com.bestcem.xm.user.service.impl;

import com.alibaba.excel.util.StringUtils;
import com.bestcem.xm.common.core.uitls.DateUtil;
import com.bestcem.xm.user.config.properties.MailSubjectNotifyTitleEnumProperties;
import com.bestcem.xm.user.config.properties.SettingProperties;
import com.bestcem.xm.user.config.properties.UserEmailProperties;
import com.bestcem.xm.user.constant.CommonConstant;
import com.bestcem.xm.user.constant.SystemConstant;
import com.bestcem.xm.user.enums.NotifyStatusEnum;
import com.bestcem.xm.user.enums.NotifyTypeEnum;
import com.bestcem.xm.user.service.MailService;
import com.bestcem.xm.user.service.dto.order.RecordToOmDTO;
import com.bestcem.xm.user.util.business.StringFormatUtil;
import com.bestcem.xm.user.util.business.UserUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;
import javax.validation.constraints.NotNull;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 发送邮件实现类
 *
 * @author panyun <yun.pan@idiaoyan.com>
 * @version v1.0
 * @date 2022/3/11 10:56
 */
@Slf4j
@Service
public class MailServiceImpl implements MailService {

    @Resource
    private UserEmailProperties userEmailProperties;

    @Resource
    private MailSubjectNotifyTitleEnumProperties mailSubjectNotifyTitleEnumProperties;

    @Resource
    private UserUtil userUtil;

    @Resource
    private SettingProperties settingProperties;

    @Override
    public boolean sendEmailAndEnclosure(String[] to, String[] cc, String subject, String content, Map<String, File> enclosureFiles) {
        // 默认发送邮箱
        String from = userEmailProperties.getDefaultEmail();
        JavaMailSenderImpl javaMailSender = this.generateSender();

        try {
            MimeMessage message = javaMailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message, true, String.valueOf(StandardCharsets.UTF_8));
            helper.setFrom(from);
            helper.setTo(to);
            if (Objects.nonNull(cc) && cc.length > 0) {
                helper.setCc(cc);
            }
            helper.setSubject(subject);
            helper.setText(content, false);
            // 设置附件
            if (Objects.nonNull(enclosureFiles) && !enclosureFiles.isEmpty()) {
                for (Map.Entry<String, File> entry : enclosureFiles.entrySet()) {
                    helper.addAttachment(MimeUtility.encodeText(entry.getKey(), String.valueOf(StandardCharsets.UTF_8), null), entry.getValue());
                }
            }
            javaMailSender.send(message);
        } catch (Exception e) {
            log.error("[USER] 发送邮件至{}异常,发件者: {} ;{}", to, javaMailSender.getUsername(), e.getMessage());
            return false;
        }
        return true;
    }

    @Override
    public boolean sendEmail(@NotNull String[] to, String subject, @NotNull String fileName, HashMap<String, Object> map) {
        // 默认发送邮箱
        String from = userEmailProperties.getDefaultEmail();
        // 获取邮件发送服务类
        JavaMailSenderImpl javaMailSender = this.generateSender();
        return sendEmail(javaMailSender, from, to, subject, fileName, map);
    }

    @Override
    public boolean sendEmail(@NotNull String[] to, String subject, String content) {
        // 默认发送邮箱
        String from = userEmailProperties.getDefaultEmail();
        // 获取邮件发送服务类
        JavaMailSenderImpl javaMailSender = this.generateSender();

        if (log.isInfoEnabled()) {
            log.info("[USER] 开始发送邮件0,变量:{} ", javaMailSender.toString());
        }

        try {
            MimeMessage message = javaMailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message, true, String.valueOf(StandardCharsets.UTF_8));
            helper.setFrom(from);
            helper.setTo(to);
            helper.setSubject(subject);
            helper.setText(content, true);
            javaMailSender.send(message);
        } catch (Exception e) {
            if (log.isInfoEnabled()) {
                log.error("[USER] 发送邮件至{}异常,发件者: {} ;{}", to, javaMailSender.getUsername(), e.getMessage());
            }
            return false;
        }

        if (log.isInfoEnabled()) {
            log.info("[USER] 邮件已发送至{},发件者: {} ;", to, javaMailSender.getUsername());
        }
        return true;
    }

    @Override
    public boolean emailSendAndNotifyOm(JavaMailSenderImpl javaMailSender, String from, @NotNull String[] to, String[] cc, String subject, String fileName, HashMap<String, Object> map) {
        // 默认发送邮箱
        if (StringUtils.isEmpty(from)) {
            from = userEmailProperties.getDefaultEmail();
        }
        if (Objects.isNull(javaMailSender)) {
            // 获取邮件发送服务类
            javaMailSender = this.generateSender();
        }
        // 邮件内容
        String content = buildContent(fileName, map);
        // 发送邮件
        boolean result = sendEmail2(javaMailSender, from, to, subject, content);
        if (!result) {
            return false;
        }
        // 是否需要通知om
        Object notifyTitle = map.get("notify_title");
        if (mailSubjectNotifyTitleEnumProperties.containsSubject(subject) || Objects.nonNull(notifyTitle)) {
            List<String> receive = Arrays.stream(to).collect(Collectors.toList());
            if (Objects.nonNull(cc)) {
                receive.addAll(Arrays.asList(cc));
            }
            String receiveStr = String.join(",", receive);
            String name = Objects.nonNull(notifyTitle) ? String.valueOf(notifyTitle) : mailSubjectNotifyTitleEnumProperties.getTitle(subject);
            RecordToOmDTO recordToOmDTO = new RecordToOmDTO();
            recordToOmDTO.setContent(content);
            recordToOmDTO.setName(name);
            recordToOmDTO.setOrgId(Objects.nonNull(map.get("org_id")) ? String.valueOf(map.get("org_id")) : "");
            recordToOmDTO.setReceiver(receiveStr);
            recordToOmDTO.setSender(from);
            recordToOmDTO.setType(NotifyTypeEnum.EMAIL.getType());
            recordToOmDTO.setStatus(NotifyStatusEnum.IS_SEND.getType());
            recordToOmDTO.setSendTime(DateUtil.convertDteToString(new Date(), DateUtil.NORM_DATETIME_PATTERN));
            recordToOmDTO.setParams(Objects.nonNull(map.get("render_data")) ? String.valueOf(map.get("render_data")) : "");
            userUtil.recordToOm(recordToOmDTO);
        }
        return true;
    }

    @Override
    public boolean emailSendAndNotifyOm(@NotNull String[] to,
                                        String[] cc,
                                        String subject,
                                        @NotNull String fileName,
                                        HashMap<String, Object> map) {
        return emailSendAndNotifyOm(null, null, to, cc, subject, fileName, map);
    }

    @Override
    public boolean sendEmail(JavaMailSenderImpl javaMailSender, String from, @NotNull String[] to, String subject,
                             @NotNull String fileName, HashMap<String, Object> map) {

        if (log.isInfoEnabled()) {
            log.info("[USER] 开始发送邮件1,变量:{} ", javaMailSender.toString());
        }

        try {
            MimeMessage message = javaMailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message, true, String.valueOf(StandardCharsets.UTF_8));
            helper.setFrom(from);
            helper.setTo(to);
            helper.setSubject(subject);
            helper.setText(buildContent(fileName, map), true);
            javaMailSender.send(message);
        } catch (Exception e) {
            if (log.isInfoEnabled()) {
                log.error("[USER] 发送邮件至{}异常,发件者: {} ;{}", to, javaMailSender.getUsername(), e.getMessage());
            }
            return false;
        }

        if (log.isInfoEnabled()) {
            log.info("[USER] 邮件已发送至{},发件者: {} ;", to, javaMailSender.getUsername());
        }
        return true;
    }

    /**
     * 创建邮件发送服务类
     *
     * @return org.springframework.mail.javamail.JavaMailSenderImpl
     * @author panyun <yun.pan@idiaoyan.com>
     * @date 2022/3/4 14:19
     */
    private JavaMailSenderImpl generateSender() {
        JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
        javaMailSender.setProtocol(userEmailProperties.getSmtpProtocol());
        javaMailSender.setHost(userEmailProperties.getDefaultHost());
        javaMailSender.setUsername(userEmailProperties.getDefaultEmail());
        javaMailSender.setPassword(userEmailProperties.getDefaultPwd());
        javaMailSender.setDefaultEncoding(userEmailProperties.getSmtpEncoding());
        Properties properties = new Properties();
        // 设置超时时间
        properties.setProperty(CommonConstant.MAIL_SMTP_TIMEOUT, userEmailProperties.getSmtpTimeout());

        // 如果是ssl的话,需要设置以下属性
        properties.setProperty(CommonConstant.MAIL_SMTP_AUTH, userEmailProperties.getSmtpAuth());
        properties.setProperty(CommonConstant.MAIL_SMTP_SOCKETFACTORY_CLASS,
                userEmailProperties.getSmtpSocketFactoryClass());
        properties.setProperty(CommonConstant.MAIL_SMTP_SOCKETFACTORY_PORT,
                String.valueOf(userEmailProperties.getDefaultPort()));

        javaMailSender.setJavaMailProperties(properties);
        return javaMailSender;
    }

    @Override
    public JavaMailSenderImpl buildMailSender(String host, Integer port, String userName, String password) {
        JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
        javaMailSender.setProtocol(userEmailProperties.getSmtpProtocol());
        javaMailSender.setHost(host);
        javaMailSender.setUsername(userName);
        javaMailSender.setPassword(password);
        javaMailSender.setDefaultEncoding(userEmailProperties.getSmtpEncoding());
        Properties properties = new Properties();
        // 设置超时时间
        properties.setProperty(CommonConstant.MAIL_SMTP_TIMEOUT, userEmailProperties.getSmtpTimeout());

        // 如果是ssl的话,需要设置以下属性
        properties.setProperty(CommonConstant.MAIL_SMTP_AUTH, userEmailProperties.getSmtpAuth());
        properties.setProperty(CommonConstant.MAIL_SMTP_SOCKETFACTORY_CLASS,
                userEmailProperties.getSmtpSocketFactoryClass());
        properties.setProperty(CommonConstant.MAIL_SMTP_SOCKETFACTORY_PORT,
                String.valueOf(userEmailProperties.getDefaultPort()));

        javaMailSender.setJavaMailProperties(properties);
        return javaMailSender;
    }

    /**
     * 读取html页面，并替换参数
     *
     * @param fileName 模板文件
     * @param map      参数
     * @return java.lang.String
     * @author panyun <yun.pan@idiaoyan.com>
     * @date 2022/3/7 11:23
     */
    @Override
    public String buildContent(String fileName, HashMap<String, Object> map) {
        //加载邮件html模板
        try (InputStream inputStream = this.getClass().getResourceAsStream(fileName);
             BufferedReader fileReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
            StringBuilder builder = new StringBuilder();
            String line = "";

            while ((line = fileReader.readLine()) != null) {
                builder.append(line);
            }
            //替换参数
            return StringFormatUtil.format(builder.toString(), map);
        } catch (Exception e) {
            log.error("读取文件失败，fileName:{}", fileName, e);
        }
        return "";
    }

    private boolean sendEmail2(JavaMailSenderImpl javaMailSender, String from, @NotNull String[] to, String subject,
                               String content) {

        if (!SystemConstant.PROD_APP_ENV.equals(settingProperties.getAppEnv())) {
            for (String email : to) {
                boolean flg = userUtil.checkUserIsInner(null, email, "");
                if (!flg) {
                    if (log.isInfoEnabled()) {
                        log.info("[USER] 非生产环境，非内部用户，不发送邮件:{} ", email);
                    }
                    return true;
                }
            }
        }

        if (log.isInfoEnabled()) {
            log.info("[USER] 开始发送邮件2,变量:{} ", javaMailSender.toString());
        }

        try {
            MimeMessage message = javaMailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message, true, String.valueOf(StandardCharsets.UTF_8));
            helper.setFrom(from);
            helper.setTo(to);
            helper.setSubject(subject);
            helper.setText(content, true);
            javaMailSender.send(message);
        } catch (Exception e) {
            log.error("[USER] 发送邮件至{}异常,发件者: {}", to, javaMailSender.getUsername(), e);
            return false;
        }

        if (log.isInfoEnabled()) {
            log.info("[USER] 邮件已发送至{},发件者: {} ;", to, javaMailSender.getUsername());
        }
        return true;
    }
}
